#include "logger.h"
#include "logger_manager.h"
#include "./detail/file_appender.h"

#ifdef LOGGER_NET_APPENDER
#include "./detail/tcp_appender.h"
#include "./detail/udp_appender.h"
#endif //

#include "./detail/console_appender.h"

#include <boost/bind.hpp>

using namespace vpm::log; 

LoggerManager* LoggerManager::m_loggerManager; 

LoggerManager & LoggerManager::instance()
{
	if (m_loggerManager == NULL)
	{
		m_loggerManager = new LoggerManager(); 
	}
	return *m_loggerManager;
}

LoggerManager::LoggerManager()
{
    boost::shared_ptr<ConsoleAppenderConfig> appenderConfig (new ConsoleAppenderConfig());
	LogAppender * pAppender = new ConsoleAppender(appenderConfig);
	m_logAppenders.push_back(pAppender);
	//question here, is the bind support to bind the base pointer to derived class ? 	
	LogMonitor::instance().attach(boost::bind(&ConsoleAppender::append_message,(ConsoleAppender *)pAppender,_1));
}


int LoggerManager::start_logger()
{
	LogMonitor::instance().start_monitor();
	for (LogAppenders::iterator itr = this->m_logAppenders.begin(); itr != m_logAppenders.end(); ++itr)
	{
		(*itr)->open();
	}
	return 0; 
}

void LoggerManager::stop_logger()
{
	LogMonitor::instance().stop_monitor();
	for (LogAppenders::iterator itr = this->m_logAppenders.begin(); itr != m_logAppenders.end(); ++itr)
	{
		(*itr)->close();
	}	
}


void LoggerManager::register_logger(const std::string & module, Logger * logger)
{
	this->m_loggers[module] = logger; 	
}

void LoggerManager::unregister_logger(const std::string & module)
{
	std::map<std::string, Logger *>::iterator itr = m_loggers.find(module);
	if (itr != m_loggers.end())
	{
		m_loggers.erase(itr); 
	}

	if (m_loggers.empty())
	{
		delete LoggerManager::m_loggerManager; 
	}
}

Logger * LoggerManager::get_logger(const std::string & module)
{
	return this->m_loggers[module];
}

void LoggerManager::set_level(const std::string & module, LogConfig::LogLevel lv, bool flag/* on/Off */ )
{
	Logger *pLogger = m_loggers[module]; 
	if (pLogger )
	{
		pLogger->set_level(lv,flag);
	}	
}

//it's not safe to invoke this on runtime. so , must stop all logger then add new appender
void LoggerManager::add_file_appender( boost::shared_ptr<FileAppenderConfig>  cfg)
{
	LogAppender * pAppender = new FileAppender(cfg);
	m_logAppenders.push_back(pAppender);
	//question here, is the bind support to bind the base pointer to derived class ? 	
	LogMonitor::instance().attach(boost::bind(&FileAppender::append_message,(FileAppender *)pAppender,_1));
}

#ifdef LOGGER_NET_APPENDER

void LoggerManager::add_tcp_appender( int port ,const std::string & ipaddr)
{
	LogAppender * pAppender = new TcpAppender();
	m_logAppenders.push_back(pAppender);
	LogMonitor::instance().attach(boost::bind(&TcpAppender::append_message,(TcpAppender *)pAppender,_1));
}


void LoggerManager::add_udp_appender( int port ,const std::string & ipaddr)
{
	LogAppender * pAppender = new UdpAppender(port,ipaddr);
	m_logAppenders.push_back(pAppender);
	LogMonitor::instance().attach(boost::bind(&UdpAppender::append_message,(UdpAppender *)pAppender,_1));
}

#endif //

